home *** CD-ROM | disk | FTP | other *** search
/ Network CD 1 / Network CD.iso / fredfish / 901-910 / ff907 / cyberpager / source / source.lha / dialer / send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-09  |  12.0 KB  |  519 lines

  1. #include "/include/memory.h"
  2.  
  3. #include "dialer.h"
  4.  
  5. BOOL online;
  6.  
  7. static UBYTE packetBuf[1024];
  8. static UBYTE safePacketBuf[8 * sizeof(packetBuf)];
  9.  
  10. static const UBYTE hexTable[] = "0123456789ABCDEF";
  11.  
  12. static LONG safeBufIndex = 0;
  13. static BOOL lastSafeSpecial;
  14. static BOOL lastSafeHex;
  15.  
  16.  /*
  17.   * add a character to the safe buf.  insert an intelligent name for special
  18.   * characers and convert unprintable to hex values. calling with a parameter
  19.   * of -1 means to close the buffer off.
  20.   */
  21.  
  22. static WORD AddToSafeBuf(WORD c)
  23. {
  24.     STRPTR specialName;
  25.  
  26.     if (safeBufIndex == 0) {
  27.         lastSafeSpecial = TRUE;
  28.         lastSafeHex = FALSE;
  29.     }
  30.  
  31.     if (c == -1) {
  32.         if (safeBufIndex == 0 || lastSafeSpecial == FALSE) {
  33.             if (safeBufIndex == 0)
  34.                 safePacketBuf[safeBufIndex++] = '\"';
  35.  
  36.             safePacketBuf[safeBufIndex++] = '\"';
  37.         }
  38.  
  39.         safePacketBuf[safeBufIndex] = '\0';
  40.         safeBufIndex = 0;
  41.     }
  42.     else {
  43.         switch (c) {
  44.         case HSHAKE_STX:
  45.             specialName = "STX";
  46.             break;
  47.  
  48.         case HSHAKE_ETX:
  49.             specialName = "ETX";
  50.             break;
  51.  
  52.         case HSHAKE_EOT:
  53.             specialName = "EOT";
  54.             break;
  55.  
  56.         case HSHAKE_ACK:
  57.             specialName = "ACK";
  58.             break;
  59.  
  60.         case HSHAKE_NAK:
  61.             specialName = "NAK";
  62.             break;
  63.  
  64.         case HSHAKE_ETB:
  65.             specialName = "ETB";
  66.             break;
  67.  
  68.         case HSHAKE_RS:
  69.             specialName = "RS";
  70.             break;
  71.  
  72.         case HSHAKE_US:
  73.             specialName = "US";
  74.             break;
  75.  
  76.         case '\r':
  77.             specialName = "CR";
  78.             break;
  79.  
  80.         case '\x1B':
  81.             specialName = "ESC";
  82.             break;
  83.  
  84.         default:
  85.             specialName = NULL;
  86.             break;
  87.         }
  88.  
  89.         if (specialName != NULL) {
  90.             if (lastSafeSpecial == FALSE) {
  91.                 safePacketBuf[safeBufIndex++] = '\"';
  92.                 lastSafeSpecial = TRUE;
  93.             }
  94.  
  95.             if (safeBufIndex)
  96.                 safePacketBuf[safeBufIndex++] = ' ';
  97.  
  98.             while (*specialName)
  99.                 safePacketBuf[safeBufIndex++] = *specialName++;
  100.  
  101.             lastSafeHex = FALSE;
  102.         }
  103.         else {
  104.             if (lastSafeSpecial) {
  105.                 if (safeBufIndex)
  106.                     safePacketBuf[safeBufIndex++] = ' ';
  107.  
  108.                 safePacketBuf[safeBufIndex++] = '\"';
  109.  
  110.                 lastSafeSpecial = FALSE;
  111.             }
  112.  
  113.             if (isprint(c)) {
  114.  
  115.                 /*
  116.                  * check to see if the last character was a
  117.                  * hex value.  if so, see if the current
  118.                  * characer is a valid hex digit.  if so,
  119.                  * insert " " so that one doesn't get
  120.                  * confused reading the translated output as
  121.                  * otherwise it would look like a larger hex
  122.                  * digit has been specified than really was.
  123.                  */
  124.                 if (lastSafeHex) {
  125.                     if (isxdigit(c)) {
  126.                         safePacketBuf[safeBufIndex++] = '\"';
  127.                         safePacketBuf[safeBufIndex++] = ' ';
  128.                         safePacketBuf[safeBufIndex++] = '\"';
  129.                     }
  130.  
  131.                     lastSafeHex = FALSE;
  132.                 }
  133.  
  134.                 if (c == '\"')
  135.                     safePacketBuf[safeBufIndex++] = '\\';
  136.  
  137.                 safePacketBuf[safeBufIndex++] = c;
  138.             }
  139.             else {
  140.                 safePacketBuf[safeBufIndex++] = '\\';
  141.                 safePacketBuf[safeBufIndex++] = 'x';
  142.                 safePacketBuf[safeBufIndex++] = hexTable[(c >> 4) & 0xF];
  143.                 safePacketBuf[safeBufIndex++] = hexTable[c & 0xF];
  144.                 lastSafeHex = TRUE;
  145.             }
  146.         }
  147.     }
  148.  
  149.     return c;
  150. }
  151.  
  152. static LONG GetPacket(STRPTR errorMsg)
  153. {
  154.     LONG index;
  155.     UWORD c;
  156.  
  157.     safeBufIndex = index = 0;
  158.  
  159.     while (c = SerGetRawChar(20)) {
  160.         if (c == TIMEOUT) {
  161.             ErrorMsg("%s: timed out trying to read packet from service.", errorMsg);
  162.             ULog(ph, -1, "%s: timed out trying to read packet from service.", errorMsg);
  163.             return -1;
  164.         }
  165.         else if (c == '\n')
  166.             continue;
  167.         else if (c == '\r')
  168.             break;
  169.  
  170.         packetBuf[index++] = AddToSafeBuf(c);
  171.  
  172.         if (index == (sizeof(packetBuf) - 2)) {
  173.             ErrorMsg("%s: panic attack - packet from service too long.", errorMsg);
  174.             ULog(ph, -1, "%s: panic attack - packet from service too long.", errorMsg);
  175.             return -2;
  176.         }
  177.     }
  178.  
  179.     packetBuf[index] = '\0';
  180.     AddToSafeBuf(-1);
  181.  
  182.     ULog(ph, 5, "getpacket: got %s", safePacketBuf);
  183.  
  184.     return index;
  185. }
  186.  
  187. #define MAX_LOGIN_RETRIES (5)
  188.  
  189. static int DialService(PagerService_t * svc)
  190. {
  191.     int retries;
  192.     LONG len;
  193.     STRPTR ptr;
  194.  
  195.     SwitchBaud(svc->svc_BaudRate);
  196.  
  197.     if (!InitModem())
  198.         return 2;
  199.  
  200.     SerWrite(svc->svc_Phone, strlen(svc->svc_Phone));
  201.     SerPutChar('\r');
  202.  
  203.     ULog(ph, -1, "dialed %s (%s) on modem %ld", svc->svc_Name, svc->svc_Phone, openedModem);
  204.  
  205.     if (SerWaitString("CONNECT", 60)) {
  206.         online = TRUE;
  207.  
  208.         /* eat up to the newline after the connect message */
  209.  
  210.         SerWaitString("\r\n", 1);
  211.  
  212.         Delay(TICKS_PER_SECOND);
  213.  
  214.         /* first look for the ID= prompt */
  215.  
  216.         for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  217.             SerPutChar('\r');
  218.  
  219.             if (SerWaitString("ID=", 2))
  220.                 break;
  221.         }
  222.  
  223.         if (retries == MAX_LOGIN_RETRIES) {
  224.             ErrorMsg("login failed: no \"ID=\" from the service.");
  225.             ULog(ph, -1, "login failed: no \"ID=\" from the service.");
  226.             return 4;
  227.         }
  228.  
  229.         /* eat any characters trailing the ID= prompt */
  230.  
  231.         while (SerGetRawChar(1) != TIMEOUT) ;
  232.  
  233.         /* now try and log in in automatic mode */
  234.  
  235.         for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  236.             SerWrite("\x1B" "PG1000000\r", 11);
  237.  
  238.             if ((len = GetPacket("login failed")) < 0)
  239.                 return 4;
  240.             else {
  241.                 if (len == 1 && packetBuf[0] == HSHAKE_ACK) {
  242.                     for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  243.                         if ((len = GetPacket("login failed")) < 0)
  244.                             return 4;
  245.                         else if (packetBuf[0] == '\x1B' && packetBuf[1] == '[' && packetBuf[2] == 'p') {
  246.                             ULog(ph, -1, "login successful");
  247.                             return 0;
  248.                         }
  249.                     }
  250.  
  251.                     ErrorMsg("login failed: retry limit exceeded");
  252.                     ULog(ph, -1, "login failed: retry limit exceeded");
  253.                     return 4;
  254.                 }
  255.                 else if (len == 1 && packetBuf[0] == HSHAKE_NAK)
  256.                     continue;
  257.                 else if (len == 2 && packetBuf[0] == '\x1B' && packetBuf[1] == HSHAKE_EOT) {
  258.                     ErrorMsg("login failed: service refused connection.");
  259.                     ULog(ph, -1, "login failed: service refused connection.");
  260.                     return 4;
  261.                 }
  262.                 else if (packetBuf[0]) {
  263.                     ptr = packetBuf;
  264.  
  265.                     while (isspace(*ptr))
  266.                         ptr++;
  267.  
  268.                     if (ptr[0] == 'I' && ptr[1] == 'D' && ptr[2] == '=') {
  269.                         retries--;
  270.                     }
  271.                     else {
  272.                         ErrorMsg("login: unknown packet received - %s", safePacketBuf);
  273.                         ULog(ph, -1, "login: unknown packet received - %s", safePacketBuf);
  274.                     }
  275.                 }
  276.             }
  277.         }
  278.  
  279.         ErrorMsg("login failed: retry limit exceeded");
  280.         ULog(ph, -1, "login failed: retry limit exceeded");
  281.         return 4;
  282.     }
  283.     else {
  284.         ErrorMsg("login failed: no carrier detected.");
  285.         ULog(ph, -1, "login failed: no carrier detected.");
  286.         return 4;
  287.     }
  288. }
  289.  
  290. static UBYTE inputBuffer[256];
  291.  
  292. static const UBYTE checkSumTable[] = "0123456789:;<=>?";
  293.  
  294. static int SendBlock(void)
  295. {
  296.     int sum;
  297.     int i, c;
  298.     int retries;
  299.     LONG len;
  300.  
  301.     sum = safeBufIndex = i = 0;
  302.  
  303.     while (c = inputBuffer[i++])
  304.         sum += AddToSafeBuf(c);
  305.  
  306.     i--;
  307.  
  308.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[(sum >> 8) & 0xF]);
  309.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[(sum >> 4) & 0xF]);
  310.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[sum & 0xF]);
  311.     inputBuffer[i++] = AddToSafeBuf('\r');
  312.     AddToSafeBuf(-1);
  313.  
  314.     ULog(ph, 4, "sendblock: sent %s", safePacketBuf);
  315.  
  316.     for (retries = 0; retries < 100; retries++) {
  317.         SerWrite(inputBuffer, i);
  318.  
  319.         if ((len = GetPacket("sendblock failed")) < 0)
  320.             return 1;
  321.         else {
  322.             if (len == 1 && packetBuf[0] == HSHAKE_ACK)
  323.                 return 0;
  324.             else if (len == 1 && packetBuf[0] == HSHAKE_NAK) {
  325.                 ULog(ph, 2, "sendblock: received nak -- retrying");
  326.                 continue;
  327.             }
  328.             else if (len == 1 && packetBuf[0] == HSHAKE_RS) {
  329.                 ErrorMsg("sendblock failed: service rejected block");
  330.                 ULog(ph, -1, "sendblock failed: service rejected block");
  331.                 return 3;
  332.             }
  333.             else if (len == 2 && packetBuf[0] == '\x1B' && packetBuf[1] == HSHAKE_EOT) {
  334.                 ErrorMsg("sendblock failed: service requested hangup");
  335.                 ULog(ph, -1, "sendblock failed: service requested hangup");
  336.             }
  337.             else if (packetBuf[0]) {
  338.                 ErrorMsg("sendblock: unknown packet received - %s", safePacketBuf);
  339.                 ULog(ph, -1, "sendblock: unknown packet received - %s", safePacketBuf);
  340.             }
  341.         }
  342.     }
  343.  
  344.     ErrorMsg("sendblock failed: retry limit exceeded");
  345.     ULog(ph, -1, "sendblock failed: retry limit exceeded");
  346.  
  347.     return 1;
  348. }
  349.  
  350. static int ProcessSpoolFile(PagerService_t * svc, BPTR fh, STRPTR spoolFileName, STRPTR nameBuffer, STRPTR pinBuffer)
  351. {
  352.     LONG tag, blockLen;
  353.     int readOffset;
  354.     int result;
  355.     int pageCount;
  356.  
  357.     /* make sure we are connected to the service. */
  358.  
  359.     if (!online)
  360.         if (result = DialService(svc))
  361.             return result;
  362.  
  363.     /* loop sending pages in the spoolfile to the service */
  364.  
  365.     for (tag = FGetC(fh), pageCount = result = 0; !result && tag != END_OF_SPOOL; pageCount++) {
  366.         if ((tag != PAGE_START) || ((tag = FGetC(fh)) == EOF)) {
  367.             ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  368.             ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  369.             return 3;
  370.         }
  371.  
  372.         inputBuffer[0] = HSHAKE_STX;
  373.         strcpy(&inputBuffer[1], pinBuffer);
  374.         readOffset = strlen(inputBuffer);
  375.         inputBuffer[readOffset++] = '\r';
  376.  
  377.         for (; !result && tag != PAGE_END;) {
  378.             if ((tag != BLOCK_START) ||
  379.                 ((blockLen = FGetC(fh)) == EOF) || (blockLen + readOffset + 1 > 250) ||
  380.                 (FRead(fh, &inputBuffer[readOffset], 1, blockLen) != blockLen) ||
  381.                 ((tag = FGetC(fh)) != BLOCK_END) || ((tag = FGetC(fh)) == EOF)) {
  382.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  383.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  384.                 return 3;
  385.             }
  386.  
  387.             if (tag == PAGE_END) {
  388.                 inputBuffer[readOffset + blockLen++] = '\r';
  389.                 inputBuffer[readOffset + blockLen++] = HSHAKE_ETX;
  390.             }
  391.             else
  392.                 inputBuffer[readOffset + blockLen++] = HSHAKE_US;
  393.  
  394.             inputBuffer[readOffset + blockLen] = 0;
  395.  
  396.             result = SendBlock();
  397.  
  398.             readOffset = 1;
  399.         }
  400.  
  401.         tag = FGetC(fh);
  402.     }
  403.  
  404.     if (!result)
  405.         ULog(ph, -1, "delivered message to %s (%s) in %ld page%s", pinBuffer, nameBuffer, pageCount, (pageCount == 1 ? "" : "s"));
  406.  
  407.     return result;
  408. }
  409.  
  410. static STRPTR ReadLongItem(BPTR fh, STRPTR spoolFileName)
  411. {
  412.     LONG longBuf;
  413.     STRPTR buffer;
  414.  
  415.     if (FRead(fh, &longBuf, sizeof(longBuf), 1) == 1) {
  416.         if (buffer = MyAllocVec(longBuf + 1)) {
  417.             if (FRead(fh, buffer, 1, longBuf) == longBuf) {
  418.                 buffer[longBuf] = '\0';
  419.                 return buffer;
  420.             }
  421.             else {
  422.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  423.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  424.             }
  425.  
  426.             MyFreeVec(buffer);
  427.         }
  428.         else
  429.             ErrorMsg("out of memory!");
  430.     }
  431.     else {
  432.         ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  433.         ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  434.     }
  435.  
  436.     return buffer;
  437. }
  438.  
  439. static UBYTE RenameBuf[FILENAME_BUF_SIZE];
  440.  
  441. int SendSpoolFile(PagerService_t * svc, STRPTR spoolFileName)
  442. {
  443.     BPTR fh;
  444.     STRPTR nameBuffer, pinBuffer;
  445.     int result;
  446.  
  447.     result = 4;
  448.  
  449.     if (LockFile(ph, spoolFileName)) {
  450.         if (fh = Open(spoolFileName, MODE_OLDFILE)) {
  451.             result = 3;
  452.  
  453.             if (FRead(fh, inputBuffer, 1, strlen(SPOOLMAGIC) + 1) == strlen(SPOOLMAGIC) + 1) {
  454.                 if (strcmp(inputBuffer, SPOOLMAGIC) == 0) {
  455.                     if (nameBuffer = ReadLongItem(fh, spoolFileName)) {
  456.                         if (pinBuffer = ReadLongItem(fh, spoolFileName)) {
  457.                             result = ProcessSpoolFile(svc, fh, spoolFileName, nameBuffer, pinBuffer);
  458.  
  459.                             MyFreeVec(pinBuffer);
  460.                         }
  461.  
  462.                         MyFreeVec(nameBuffer);
  463.                     }
  464.                 }
  465.                 else {
  466.                     ErrorMsg("\"%s\" is not a valid spool file", spoolFileName);
  467.                     ULog(ph, -1, "\"%s\" is not a valid spool file", spoolFileName);
  468.                 }
  469.             }
  470.             else {
  471.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  472.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  473.             }
  474.  
  475.             Close(fh);
  476.         }
  477.         else {
  478.             ErrorMsg("couldn't open spool file \"%s\"", spoolFileName);
  479.             ULog(ph, -1, "couldn't open spool file \"%s\"", spoolFileName);
  480.         }
  481.  
  482.         UnLockFile(ph, spoolFileName);
  483.     }
  484.     else {
  485.         ErrorMsg("couldn't lock spool file \"%s\"", spoolFileName);
  486.         ULog(ph, -1, "couldn't lock spool file \"%s\"", spoolFileName);
  487.     }
  488.  
  489.     /*
  490.      * if the spool file is bad (result = 3) then rename it so we don't
  491.      * get hung up on it.  in this case we return 0 so that we can
  492.      * continue sending other files while on-line
  493.      */
  494.  
  495.     if (result == 3) {
  496.         strcpy(RenameBuf, spoolFileName);
  497.         strcat(RenameBuf, ".bad");
  498.  
  499.         DeleteFile(RenameBuf);    /* sanity check */
  500.  
  501.         if (Rename(spoolFileName, RenameBuf) == DOSTRUE) {
  502.             ULog(ph, -1, "renamed \"%s\" to \"%s\".", spoolFileName, RenameBuf);
  503.             result = 0;
  504.         }
  505.         else
  506.             ULog(ph, -1, "unable to rename \"%s\" to \"%s\".", spoolFileName, RenameBuf);
  507.     }
  508.  
  509.     /*
  510.      * if we are all done and sent the spool file without any trouble
  511.      * then we need to delete the file
  512.      */
  513.  
  514.     if (!result)
  515.         DeleteFile(spoolFileName);
  516.  
  517.     return result;
  518. }
  519.